/*
 * Copyright (C) 2013 Daniel Treffenstädt <daniel@treffenstaedt.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */


#ifndef O_VECTOR3D_H
#define O_VECTOR3D_H

#include "../OGlobal.h"

#include <OGRE/OgreVector3.h>

O_START_NAMESPACE

// +++ forward declarations
class Degree;
class Polar3D;
// --- forward declarations

/**
 * @brief The Vector3D class
 */
class O_EXPORT Vector3D
{
private:
	/**
	 * @brief contains the x component
	 */
	double			m_x;
	/**
	 * @brief contains the y component
	 */
	double			m_y;
	/**
	 * @brief contains the z component
	 */
	double			m_z;
	/**
	 * @brief contains if the vector is valid
	 */
	bool			m_valid;

public:
	/**
	 * @brief Constructs an invalid Vector3D object
	 */
	Vector3D();
	/**
	 * @brief Constructs a valid Vector3D object
	 * @param x component
	 * @param y component
	 * @param z component
	 */
	Vector3D(double x, double y, double z);

	/**
	 * @brief Constructs a valid Vector3D object from an Ogre::Vector3
	 * @param Ogre::Vector3 object
	 */
	Vector3D(Ogre::Vector3 v);

	/**
	 * @brief valid
	 * @return true if the objectis valid
	 */
	bool valid();

	/**
	 * @brief gets the x component
	 * @return x component
	 */
	double x();
	/**
	 * @brief gets the y component
	 * @return y component
	 */
	double y();
	/**
	 * @brief gets the z component
	 * @return z component
	 */
	double z();

	/**
	 * @brief calculates the magnitude
	 * @return length of the vector
	 */
	double magnitude();

	/**
	 * @brief calculates the Polar coordinates from the vector
	 * @return Polar3D object
	 */
	Polar3D toPolar();

	/**
	 * @brief creates an Ogre::Vector3 object
	 * @return Ogre::Vector3 object
	 */
	Ogre::Vector3 toOgre();

	/**
	 * @brief calculates the cross product of two vectors
	 * @param other vector
	 * @return cross product of two vectors
	 */
	Vector3D crossProduct(Vector3D v);

	/**
	 * @brief calculates the dot product of two vectors
	 * @param other vector
	 * @return dot product of two vectors
	 */
	double dotProduct(Vector3D v);

	/**
	 * @brief rotates the vector horizontally
	 * @param angle
	 */
	void rotateH(Degree d);

	/**
	 * @brief rotates the vector vertically
	 * @param angle
	 */
	void rotateV(Degree d);


	/**
	 * @brief operator +=
	 * @param v
	 */
	void operator+= (Vector3D v);
	/**
	 * @brief operator +
	 * @param v
	 * @return
	 */
	Vector3D operator+ (Vector3D v);

	/**
	 * @brief operator -=
	 * @param v
	 */
	void operator-= (Vector3D v);
	/**
	 * @brief operator -
	 * @param v
	 * @return
	 */
	Vector3D operator- (Vector3D v);

	/**
	 * @brief operator <
	 * @param v
	 * @return
	 */
	bool operator< (Vector3D v);
	/**
	 * @brief operator <=
	 * @param v
	 * @return
	 */
	bool operator<= (Vector3D v);

	/**
	 * @brief operator >
	 * @param v
	 * @return
	 */
	bool operator> (Vector3D v);
	/**
	 * @brief operator >=
	 * @param v
	 * @return
	 */
	bool operator>= (Vector3D v);

	/**
	 * @brief operator ==
	 * @param v
	 * @return
	 */
	bool operator== (Vector3D v);
	/**
	 * @brief operator !=
	 * @param v
	 * @return
	 */
	bool operator!= (Vector3D v);

	/**
	 * @brief operator =
	 * @param v
	 */
	void operator= (Vector3D v);

	/**
	 * @brief operator =
	 * @param v
	 */
	void operator= (Ogre::Vector3 v);

	/**
	 * @brief operator *=
	 * @param a
	 */
	void operator*= (double a);
	/**
	 * @brief operator *
	 * @param a
	 * @return
	 */
	Vector3D operator* (double a);

	/**
	 * @brief operator /=
	 * @param a
	 */
	void operator/= (double a);
	/**
	 * @brief operator /
	 * @param a
	 * @return
	 */
	Vector3D operator/ (double a);

	/**
	 * @brief operator -
	 * @return
	 */
	Vector3D operator- ();
};

O_END_NAMESPACE

#endif // O_VECTOR3D_H
